<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      const PENDING = "pending";
      const FUFILLED = "fufilled";
      const REJECTED = "rejected";
      class MyPromise {
        constructor(enctor) {
          try {
            enctor(this.resolve, this.reject);
          } catch (e) {
            this.reject(e);
          }
        }
        status = PENDING; // 状态
        value = undefined; // 成功的值
        reason = undefined; //失败的值
        callBackArr = []; //储存成功的回调函数
        callBackArrReject = []; //储存失败的回调函数
        resolve = (value) => {
          if (this.status !== PENDING) return;
          this.status = FUFILLED;
          this.value = value;
          if (this.callBackArr.length != 0) {
            //判断储存的数组有没有成功回调函数 如果有就循环调用 调用一个删除一个
            // this.callBackArr.shift()(value)
            this.callBackArr.forEach((item) => {
              let x = item();
            });
          }
          this.callBackArr = [];
        };
        reject = (reason) => {
          if (this.status !== PENDING) return;
          this.status = REJECTED;
          this.reason = reason;
          if (this.callBackArrReject.length != 0) {
            for (let i = 0; i < this.callBackArrReject.length; i++) {
              // let y=this.callBackArrReject[i](reason)
              let x = this.callBackArrReject[i]();
            }
            this.callBackArrReject = [];
            //判断储存的数组有没有成功回调函数 如果有就循环调用 调用一个删除一个
          }
        };

        then(succsessCallback, failCallback) {
          succsessCallback = succsessCallback? succsessCallback: (value) => value;
          failCallback = failCallback? failCallback: (reason) => {throw reason;};
          let promise2 = new MyPromise((resolve, reject) => {
            if (this.status == FUFILLED) {
              setTimeout(() => {
                console.log("FUFILLED");
                try {
                  let x = succsessCallback(this.value);
                  resolvePromsise(promise2, x, resolve, reject);
                } catch (e) {
                  reject(e);
                }
              }, 0);
            } else if (this.status == REJECTED) {
              console.log("REJECTED");
              setTimeout(() => {
                try {
                  let y = failCallback(this.reason);
                  resolvePromsise(promise2, y, resolve, reject);
                } catch (e) {
                  reject(e);
                }
              });
            } else {
              this.callBackArr.push(() => {
                setTimeout(() => {
                  console.log("FUFILLED");
                  try {
                    let x = succsessCallback(this.value);
                    resolvePromsise(promise2, x, resolve, reject);
                  } catch (e) {
                    reject(e);
                  }
                }, 0);
              });
              this.callBackArrReject.push(() => {
                setTimeout(() => {
                  try {
                    let y = failCallback(this.reason);
                    resolvePromsise(promise2, y, resolve, reject);
                  } catch (e) {
                    reject(e);
                  }
                });
              });
            }
          });

          return promise2;
        }

        finally(callback) {
          return this.then(
            (value) => {
              // callback()
              return MyPromise.resolve(callback()).then(() => value);
            },
            (reason) => {
              // callback()
              return MyPromise.resolve(callback()).then(() => {
                throw reason;
              });
            }
          );
        }

        catch(failCallback) {
          return this.then(undefined, failCallback);
        }
        static all(array) {
          let result = [];
          let index = 0;

          return new MyPromise((resolve, reject) => {
            function addData(key, value) {
              result[key] = value;
              index++;
              if (index == array.length) {
                resolve(result);
              }
            }
            for (let i = 0; i < array.length; i++) {
              let current = array[i];
              if (current instanceof MyPromise) {
                //promise对象
                current.then(
                  (value) => {
                    addData(i, value);
                  },
                  (reason) => {
                    reject(reason);
                  }
                );
              } else {
                // 普通纸
                addData(i, array[i]);
              }
            }
          });
        }

        static resolve(value) {
          if (value instanceof MyPromise) {
            return value;
          } else {
            return new MyPromise((resolve, reject) => {
              resolve(value);
            });
          }
        }
      }

      function resolvePromsise(promise2, x, resolve, reject) {
        debugger;
        if (promise2 === x) {
          return reject(new TypeError("primose 报错"));
        }
        if (x instanceof MyPromise) {
          x.then(
            (value) => {
              resolve(value);
            },
            (reason) => {
              reject(reason);
            }
          );
        } else {
          resolve(x);
        }
      }

      function other() {
        return new MyPromise((resolve, reject) => {
          setTimeout(() => {
            resolve("自己延迟新创建");
          }, 2000);
        });
      }

      function other1() {
        return new MyPromise((resolve, reject) => {
          resolve("自己新创建");
        });
      }
      MyPromise.all(["a", "b", other(), other1(), "c"]).then((value) =>
        console.log(value)
      );

      //     let my=new MyPromise((resolve,reject)=>{
      //         // resolve('哈哈')
      //         // reject('失败了')
      //     //    throw new Error('primose 报错')
      //        setTimeout(()=>{
      //         resolve('成功')
      //        },2000)
      //     })
      //   var p1=  my.then(
      //         value=>{
      //             console.log('第一个')
      //             console.log(value)
      //             throw new Error('错误')
      //         },
      //         reason=>{
      //             console.log(reason)
      //             throw new Error('错误1111')
      //         }
      //     )
      //     p1.then(item=>{
      //         console.log('第二个')
      //         console.log(item)
      //     },(value)=>{
      //         console.log('第二个失败')
      //         console.log(value.message)
      //     })
    </script>
  </body>
</html>
